package client;

import static debug.Debug.DBUG;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import event.AlfaEvent;

import model.Map;

import server.Server;
import unit.Player;
import unit.Unit;
import util.IntPoint;

public class ClientControl implements Client{

			// there is another collection-type better suited for this, with max one occurance per list
	private List<Changeable> seeable;
	private Socket sock;
	private BufferedWriter out;
	private Server server;
	private ClientPlayer player;
	private boolean loggedin;
	
	public ClientControl(Socket sock, Server server){
		seeable = new ArrayList<Changeable>();
		this.server = server;
		this.sock = sock;
		try {
			out = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
		} catch (IOException e) {}
		
		server.addClient(this);
		new LoginHandeler(this, sock);
	}
	
	public BufferedReader getInput() {
		try {
			return new BufferedReader(new InputStreamReader(sock.getInputStream()));
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}
	
	public Player loggedIn(String username) {
		// TODO: get info about the user (from server/database)
		IntPoint start = new IntPoint(60, 60);
		Map m = server.getMap(15);
		
		player = new ClientPlayer(server.getID(), start, m, this, server);
		server.addUnit(player);
		loggedin=true;
		return player;
	}
	
	public void addChangeable(java.util.Map<Integer,Changeable> changedObjects) {
		for (Changeable ch : changedObjects.values()) {
			if (!seeable.contains(ch)) {
				seeable.add(ch);
			}
		}
	}
	
	public void sendUpdate(){
		if (!loggedin)
			return;
		
		for(Changeable changeable: seeable){
			sendMove(changeable);
		}
		
		List<AlfaEvent> eventlist = player.getEvents();
		
		for (AlfaEvent event: eventlist) {
			DBUG("ClientControl.sendUpdate() for Alfaevent event");
			send(event.toString());
			
		}
	}
	
	private void send(String str) {
			// DEBUG part
			int chan=0;
			if (str.startsWith("unit")) {
				chan=60;
			}
			DBUG(chan, "> "+ str);
			try {
				out.write(str);
				out.flush();
			} catch (IOException e) {
				DBUG("couldn't write, client exit");
				try { sock.close(); } catch (IOException e1) {}
				server.removeClient(this);
				server.removeUnit(player);
			}
	}
	
	public void sendMove(Changeable ch) {
		if (ch instanceof Unit) {
			Unit unit = (Unit)ch;
			StringBuilder str = new StringBuilder();
			if (unit.hasMoved()) {
				str.append("unit "+ unit.id() +" "+ unit.getPos().getX() +" "+ unit.getPos().getY());
				str.append("\n");
			}
			
			if (str.length() > 0) {
				send(str.toString());
			}
		}
	}

	@Override
	public void updatedObject(Changeable changedObj) {
		// TODO Auto-generated method stub
		
	}

	public void sendEvents(List<AlfaEvent> eventlist) {
		
	}


}
